﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Caliburn.Micro;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using DomusDotNet.Sbm.Client.SL4.Infrastructure;

namespace DomusDotNet.Sbm.Client.SL4.Tests
{
	public abstract class TestBase : Microsoft.Silverlight.Testing.SilverlightTest
	{

		static TestBase() {
			App.Current.Resources.MergedDictionaries.Add(
						new ResourceDictionary { Source = new Uri("/DomusDotNet.Sbm.Client.SL4;component/Resources/Styles.xaml", UriKind.RelativeOrAbsolute) }
					);
			App.Current.Resources.Add("toStringJoin", new StringJoinConverter());

			AppBootstrapper.ConfigureConventions();
		}

		public TestBase()
		{
			IoC.GetAllInstances = t => new object[] { };
			IoC.GetInstance = (t, k) => null;

			AssemblySource.Instance.Clear();
			AssemblySource.Instance.Add(typeof(DomusDotNet.Sbm.Client.SL4.AppBootstrapper).Assembly);

		 
		}


		#region View Assertions

		protected object LocatedViewFor(object viewModel)
		{
			return LocatedViewFor(viewModel, null);
		}
		protected object LocatedViewFor<TViewModel>()
		{
			return LocatedViewFor<TViewModel>(null);
		}
		protected object LocatedViewFor(object viewModel, object context)
		{
			return ViewLocator.LocateForModel(viewModel, null, context);
		}
		protected object LocatedViewFor<TViewModel>(object context)
		{
			return ViewLocator.LocateForModelType(typeof(TViewModel), null, context);
		}

		#endregion

		#region Coroutines testing

		protected CoroutineEnumerator TestExecutorFor(IEnumerable<IResult> coroutine)
		{
			return new CoroutineEnumerator(coroutine);
		}

		protected class CoroutineEnumerator
		{
			private readonly IEnumerator<IResult> enumerator;

			public CoroutineEnumerator(IEnumerable<IResult> enumerable)
			{
				this.enumerator = enumerable.GetEnumerator();
			}

			public CoroutineEnumerator(IEnumerator<IResult> enumerator)
			{
				this.enumerator = enumerator;
			}

			public TResult GetNext<TResult>()
			{
				while (enumerator.MoveNext())
				{
					if (enumerator.Current is TResult)
						return (TResult)enumerator.Current;
				}

				throw new InvalidOperationException("List of coroutines does not include " + typeof(TResult).Name);
			}


			public CoroutineEnumerator Next<TResult>()
			{
				return Next<TResult>(null);
			}
			public CoroutineEnumerator Next<TResult>(Action<TResult> assertions)
			{
				assertions = assertions ?? delegate { };
				var result = this.GetNext<TResult>();
				assertions(result);
				return this;
			}

			public void Finish()
			{
				while (enumerator.MoveNext()) { }
			}


		}
		#endregion
	}
}
